// src/services/websocketService.ts
import { WS_BASE_URL } from '../utils/constants';
import AsyncStorage from '@react-native-async-storage/async-storage';

type MessageHandler = (data: any) => void;
type EventHandler = (event: Event) => void;

interface WebSocketOptions {
    reconnect?: boolean;
    reconnectInterval?: number;
    maxReconnectAttempts?: number;
    heartbeatInterval?: number;
}

class WebSocketService {
    private ws: WebSocket | null = null;
    private url: string;
    private options: WebSocketOptions;
    private reconnectAttempts = 0;
    private heartbeatTimer: NodeJS.Timeout | null = null;
    private reconnectTimer: NodeJS.Timeout | null = null;
    private messageHandlers: Map<string, Set<MessageHandler>> = new Map();
    private eventHandlers: {
        open: Set<EventHandler>;
        close: Set<EventHandler>;
        error: Set<EventHandler>;
    } = {
        open: new Set(),
        close: new Set(),
        error: new Set(),
    };
    private isConnected = false;
    private pendingMessages: any[] = [];

    constructor() {
        this.url = WS_BASE_URL;
        this.options = {
            reconnect: true,
            reconnectInterval: 5000,
            maxReconnectAttempts: 5,
            heartbeatInterval: 30000,
        };
    }

    // 连接WebSocket
    async connect(options?: WebSocketOptions): Promise<void> {
        if (this.ws && this.isConnected) {
            console.log('[WebSocket] Already connected');
            return;
        }

        this.options = { ...this.options, ...options };

        const token = await AsyncStorage.getItem('token');
        if (!token) {
            throw new Error('No authentication token');
        }

        const wsUrl = `${this.url}?token=${token}`;

        return new Promise((resolve, reject) => {
            try {
                this.ws = new WebSocket(wsUrl);

                this.ws.onopen = ((event: Event) => {
                    console.log('[WebSocket] Connected');
                    this.isConnected = true;
                    this.reconnectAttempts = 0;
                    this.flushPendingMessages();
                    this.startHeartbeat();
                    this.eventHandlers.open.forEach(h => h(event));
                    resolve();
                }) as any;

                this.ws.onmessage = (event) => {
                    try {
                        const data = JSON.parse(event.data);
                        console.log('[WebSocket] Message received:', data);

                        // 处理心跳响应
                        if (data.type === 'pong') {
                            return;
                        }

                        // 触发消息处理器
                        const handlers = this.messageHandlers.get(data.type);
                        if (handlers) {
                            handlers.forEach(handler => handler(data));
                        }

                        // 触发通用消息处理器
                        const allHandlers = this.messageHandlers.get('*');
                        if (allHandlers) {
                            allHandlers.forEach(handler => handler(data));
                        }
                    } catch (error) {
                        console.error('[WebSocket] Message parse error:', error);
                    }
                };

                this.ws.onerror = (event) => {
                    console.error('[WebSocket] Error:', event);
                    this.eventHandlers.error.forEach(handler => handler(event));
                    reject(event);
                };

                this.ws.onclose = (event) => {
                    console.log('[WebSocket] Closed:', event.code, event.reason);
                    this.isConnected = false;

                    // 停止心跳
                    this.stopHeartbeat();

                    // 触发close事件处理器
                    this.eventHandlers.close.forEach(handler => handler(event));

                    // 尝试重连
                    if (this.options.reconnect && this.reconnectAttempts < this.options.maxReconnectAttempts!) {
                        this.reconnect();
                    }
                };
            } catch (error) {
                console.error('[WebSocket] Connection error:', error);
                reject(error);
            }
        });
    }

    // 断开连接
    disconnect(): void {
        if (this.reconnectTimer) {
            clearTimeout(this.reconnectTimer);
            this.reconnectTimer = null;
        }

        this.stopHeartbeat();
        this.options.reconnect = false;

        if (this.ws) {
            this.ws.close();
            this.ws = null;
        }

        this.isConnected = false;
        this.pendingMessages = [];
    }

    // 重连
    private reconnect(): void {
        this.reconnectAttempts++;
        console.log(`[WebSocket] Reconnecting... Attempt ${this.reconnectAttempts}`);

        this.reconnectTimer = setTimeout(() => {
            this.connect().catch(error => {
                console.error('[WebSocket] Reconnection failed:', error);
            });
        }, this.options.reconnectInterval);
    }

    // 发送消息
    send(type: string, data?: any): void {
        const message = {
            type,
            data,
            timestamp: Date.now(),
        };

        if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify(message));
            console.log('[WebSocket] Message sent:', message);
        } else {
            console.log('[WebSocket] Queuing message:', message);
            this.pendingMessages.push(message);
        }
    }

    // 发送待发送的消息
    private flushPendingMessages(): void {
        while (this.pendingMessages.length > 0) {
            const message = this.pendingMessages.shift();
            if (this.ws?.readyState === WebSocket.OPEN) {
                this.ws.send(JSON.stringify(message));
                console.log('[WebSocket] Pending message sent:', message);
            }
        }
    }

    // 订阅消息
    on(type: string, handler: MessageHandler): () => void {
        if (!this.messageHandlers.has(type)) {
            this.messageHandlers.set(type, new Set());
        }

        this.messageHandlers.get(type)!.add(handler);

        // 返回取消订阅函数
        return () => {
            const handlers = this.messageHandlers.get(type);
            if (handlers) {
                handlers.delete(handler);
                if (handlers.size === 0) {
                    this.messageHandlers.delete(type);
                }
            }
        };
    }

    // 订阅事件
    onEvent(event: 'open' | 'close' | 'error', handler: EventHandler): () => void {
        this.eventHandlers[event].add(handler);

        return () => {
            this.eventHandlers[event].delete(handler);
        };
    }

    // 取消订阅
    off(type: string, handler?: MessageHandler): void {
        if (handler) {
            const handlers = this.messageHandlers.get(type);
            if (handlers) {
                handlers.delete(handler);
                if (handlers.size === 0) {
                    this.messageHandlers.delete(type);
                }
            }
        } else {
            this.messageHandlers.delete(type);
        }
    }

    // 心跳机制
    private startHeartbeat(): void {
        this.stopHeartbeat();

        this.heartbeatTimer = setInterval(() => {
            if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {
                this.send('ping');
            }
        }, this.options.heartbeatInterval);
    }

    private stopHeartbeat(): void {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
    }

    // 获取连接状态
    getConnectionState(): {
        isConnected: boolean;
        readyState: number | null;
        reconnectAttempts: number;
    } {
        return {
            isConnected: this.isConnected,
            readyState: this.ws?.readyState || null,
            reconnectAttempts: this.reconnectAttempts,
        };
    }
}

export default new WebSocketService();